package com.wang.web3;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;

import com.wang.web3.base.Constant;
import com.wang.web3.bean.TianWallet;
import com.wang.web3.utils.FragmentUtils;
import com.wang.web3.utils.MyMnemonicUtils;

import org.bitcoinj.crypto.ChildNumber;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.wallet.DeterministicKeyChain;
import org.bitcoinj.wallet.DeterministicSeed;
import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Keys;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.Web3jFactory;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGetBalance;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static org.bitcoinj.crypto.HDUtils.parsePath;
import static org.web3j.crypto.WalletUtils.loadBip39Credentials;
import static org.web3j.utils.Numeric.toHexStringNoPrefixZeroPadded;

public class Main2Activity extends AppCompatActivity {


    //    @Bind(R.id.mFrameLayout)
//    FrameLayout mFrameLayout;
    HomeFragment homeFragment;
    GameInfoFragment gameInfoFragment;
    OpenBoxFragment openBoxFragment;
    BackpackFragment backpackFragment;
    NeoWalletFragment neoFragment;

    Web3j web3;
    Credentials credentials;
    TextView tvWords;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tvWords = findViewById(R.id.tvWords);
        init();
//        ButterKnife.bind(this);
        initConecation();

        homeFragment = homeFragment.newInstance("0", "0");
//        marketFragment =  marketFragment.newInstance("0","0");
        FragmentUtils.show(getSupportFragmentManager(), R.id.mFrameLayout, homeFragment);


    }

    //average green proud remember advance trick estate oblige trouble when cube person

    //初始化链接
    private void initConecation() {
        try {
            String url = "http://10.0.2.2:7545";
            web3 = Web3jFactory.build(new HttpService(url));
            //            Web3j web3 = Web3jFactory.build(new HttpService());
            Web3ClientVersion web3ClientVersion = null;

            web3ClientVersion = web3.web3ClientVersion().sendAsync().get();
            String clientVersion = web3ClientVersion.getWeb3ClientVersion();

            //设置秘钥
            credentials = Credentials.create("c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3");
//        mSerchAddress
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public void onCreateWords(View view) {

//        ApiServiceImpl apiService = new ApiServiceImpl();
//        apiService.apiConfig("wangzhe");
//        Credentials credentials;
//        try {
//            String filePath = Environment.getExternalStorageDirectory().getAbsolutePath().toString() + "";
//            String fileName = WalletUtils.generateLightNewWalletFile("12345678",new File(filePath));
//             credentials = WalletUtils.loadCredentials("12345678",filePath + "/" + fileName);
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        } catch (NoSuchProviderException e) {
//            e.printStackTrace();
//        } catch (InvalidAlgorithmParameterException e) {
//            e.printStackTrace();
//        } catch (CipherException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        String ss = makeMnemonic("");
        tvWords.setText(ss);
        TianWallet tianWallet = createETHWalletFromWords(ss);
        //noise earth debris result galaxy alcohol trust dentist match frost prize thing

    }

    private TianWallet createETHWalletFromWords(String words) {
        List<String> list = Arrays.asList(words.split("\\s+"));
        DeterministicSeed deterministicSeed = new DeterministicSeed(list, null, "", 0);
//        val wordsList = Arrays.asList(*words.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
        DeterministicKeyChain deterministicKeyChain = DeterministicKeyChain.builder().seed(deterministicSeed).build();
        String DERIVATION_PATH = "M/44H/1H/0H/0/0";
        DeterministicKey deterministicKey = deterministicKeyChain.getKeyByPath(parsePath(DERIVATION_PATH), true);
        ChildNumber childNumber = deterministicKey.getChildNumber();

//        DeterministicKey deterministicKey2 = deterministicKey.derive(1);
//        BigInteger privateKey2 = deterministicKey2.getPrivKey();
//        ECKeyPair ecKeyPair2 = ECKeyPair.create(privateKey2);
//        String address2 = Keys.getAddress(ecKeyPair2);

        BigInteger privateKey = deterministicKey.getPrivKey();

        ECKeyPair ecKeyPair = ECKeyPair.create(privateKey);


        try {
            String filePath = Environment.getExternalStorageDirectory().getAbsolutePath().toString() + "";
            String fileName = WalletUtils.generateWalletFile("123456789", ecKeyPair, new File(filePath), false);

            FileInputStream inputStream = new FileInputStream(filePath + "/" + fileName);
            byte temp[] = new byte[1024];
            StringBuilder sb = new StringBuilder("");
            int len = 0;
            while ((len = inputStream.read(temp)) > 0) {
                sb.append(new String(temp, 0, len));
            }
            String string = sb.toString();
            Log.e("tag", "------" + ecKeyPair.toString());
        } catch (CipherException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String address = Keys.getAddress(ecKeyPair);

        return new TianWallet("111", "0x" + address, Numeric.toHexStringWithPrefix(ecKeyPair.getPrivateKey()), Numeric.toHexStringWithPrefix(ecKeyPair.getPublicKey()), words);
    }


    //    private val secureRandom = secure.()
    private String makeMnemonic(String adress) {

        byte[] initialEntropy = new byte[16];
//           byte[] initialEntropy = adress.getBytes();
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(initialEntropy);

        String str = new String(initialEntropy);


//           MnemonicUtils.(initialEntropy)
        return MyMnemonicUtils.generateMnemonic(initialEntropy);
    }

    public void oneth(View view) {
        testTransation();
    }

    private String ownAddress = "0x627306090abaB3A6e1400e9345bC60c78a8BEf57";
    private String toAddress = "0x550513bece93c765f15d23409be0dee8aff3b4a3";
    private String toAddress2 = "0x8045298b54e36750c5c6eb2ef28dcc64f91a0ef3";

    //测试交易
    private void testTransation() {
        try {
            //转账人私钥

            //getNonce（这里的Nonce我也不是很明白，大概是交易的笔数吧）
            EthGetTransactionCount ethGetTransactionCount = web3.ethGetTransactionCount(
                    ownAddress, DefaultBlockParameterName.LATEST).sendAsync().get();

            BigInteger nonce = ethGetTransactionCount.getTransactionCount();

            String address = "0x627306090abaB3A6e1400e9345bC60c78a8BEf57";
//            EthFilter ethFilter1 = new EthFilter(DefaultBlockParameterName.EARLIEST,DefaultBlockParameterName.LATEST,address);
//            org.web3j.protocol.core.methods.response.EthFilter ethFilter = web3.ethNewFilter(ethFilter1).sendAsync().get();
//            EthLog ethLog = web3.ethGetFilterLogs(ethFilter.getFilterId()).sendAsync().get();
//            List<EthLog.LogResult> list = ethLog.getLogs();
//            for (int i = 0; i < list.size(); i++) {
//                EthLog.LogResult<String> logResult = list.get(i);
//                logResult.toString();
//            }

            //创建交易，这里是转0.5个以太币
            BigInteger value = Convert.toWei("0.5", Convert.Unit.ETHER).toBigInteger();
            RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
                    nonce, Constant.GAS_PRICE, Constant.GAS_LIMIT, toAddress2, value);
            String s = Numeric.toHexStringNoPrefix(new BigInteger("73613530064125488692764088905301011327046644932121419461817923175507011296891"));
            String s2 = Numeric.toHexStringNoPrefix(new BigInteger("10175637926395757106523910249560071875278690999682163026504362889059180767228099370988126534299214809433292832420560105121166985972476227966752119015915344"));
            Credentials credentials1 = Credentials.create(s, s2);
//            Credentials credentials1 = null;
//            try {
//                Credentials.create(s);
//                credentials1 = WalletUtils.loadCredentials("123456789", "/storage/emulated/0/UTC--2018-04-24T07-38-52.607--8045298b54e36750c5c6eb2ef28dcc64f91a0ef3.json");
//            } catch (IOException e) {
//                e.printStackTrace();
//            } catch (CipherException e) {
//                e.printStackTrace();
//            }

            //签名Transaction，这里要对交易做签名
            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
            String hexValue = Numeric.toHexString(signedMessage);

            //发送交易
            EthSendTransaction ethSendTransaction =
                    web3.ethSendRawTransaction(hexValue).sendAsync().get();
            String transactionHash = ethSendTransaction.getTransactionHash();

            //获得到transactionHash后就可以到以太坊的网站上查询这笔交易的状态了
            System.out.println(transactionHash);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    //离线签名
    public void onSign(View view) {

        EthGetBalance ethGetBalance1 = null;
        EthGetBalance ethGetBalance2 = null;
        try {
            ethGetBalance1 = web3.ethGetBalance(toAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
            ethGetBalance2 = web3.ethGetBalance(ownAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        BigDecimal balance = new BigDecimal(ethGetBalance1.getBalance().divide(new BigInteger("10000000000000")).toString());
        BigDecimal nbalance = balance.divide(new BigDecimal("100000"), 8, BigDecimal.ROUND_DOWN);

        BigDecimal balance2 = new BigDecimal(ethGetBalance2.getBalance().divide(new BigInteger("10000000000000")).toString());
        BigDecimal nbalance2 = balance2.divide(new BigDecimal("100000"), 8, BigDecimal.ROUND_DOWN);
        Log.e("Tag", "====");

        EthGetTransactionCount ethGetTransactionCount = null;
        try {
            ethGetTransactionCount = web3.ethGetTransactionCount(
                    toAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        BigInteger nonce = ethGetTransactionCount.getTransactionCount();

        TianWallet tianWallet = new TianWallet("111", toAddress, "73613530064125488692764088905301011327046644932121419461817923175507011296891", "10175637926395757106523910249560071875278690999682163026504362889059180767228099370988126534299214809433292832420560105121166985972476227966752119015915344",
                "pepper shine accuse reason any supply upset owner cost tool plastic predict");
        signedEthTransactionData("0x627306090abaB3A6e1400e9345bC60c78a8BEf57",
                nonce,
                Constant.GAS_PRICE,
                Constant.GAS_LIMIT,
                10.0,
                tianWallet);

    }


    public String signedEthTransactionData(String to, //转账的钱包地址
                                           BigInteger nonce,//获取到的交易次数
                                           BigInteger gasPrice, //
                                           BigInteger gasLimit, //
                                           Double value, //转账的值
                                           TianWallet tianWallet) {
        //把十进制的转换成ETH的Wei, 1ETH = 10^18 Wei
        BigDecimal realValue = Convert.toWei(value.toString(), Convert.Unit.ETHER);
        BigInteger bigInteger = realValue.toBigIntegerExact();
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
                nonce,
                gasPrice,
                gasLimit,
                to,
                realValue.toBigIntegerExact());

        //手续费= (gasPrice * gasLimit ) / 10^18 ether
//        Credentials credentials = loadBip39Credentials("123456789",tianWallet.getWords());
        Credentials credentials = Credentials.create(Numeric.toHexStringNoPrefix(new BigInteger(tianWallet.getPrivateKey())));

        //使用TransactionEncoder对RawTransaction进行签名操作
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        //转换成0x开头的字符串
        String mmm = Numeric.toHexString(signedMessage);
        try {
            EthSendTransaction ethSendTransaction = web3.ethSendRawTransaction(mmm).sendAsync().get();
            ethSendTransaction.getTransactionHash();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return mmm;
    }

    public String signedContractTransactionData(String contractAddress,//代币的智能合约地址
                                                String toAdress,//对方的地址
                                                BigInteger nonce,//获取到交易数量
                                                BigInteger gasPrice,
                                                BigInteger gasLimit,
                                                Double value,
                                                Double decimal,
                                                TianWallet tianWallet) {
        //因为每个代币可以规定自己的小数位, 所以实际的转账值=数值 * 10^小数位
        BigDecimal realValue = BigDecimal.valueOf(value * Math.pow(10.0, decimal));
        //0xa9059cbb代表某个代币的转账方法hex(transfer) + 对方的转账地址hex + 转账的值的hex
        String data = "0xa9059cbb" + toHexStringNoPrefixZeroPadded(Numeric.toBigInt(toAdress), 64) + toHexStringNoPrefixZeroPadded(realValue.toBigInteger(), 64);
        RawTransaction rawTransaction = RawTransaction.createTransaction(
                nonce,
                gasPrice,
                gasLimit,
                contractAddress,
                data);

        Credentials credentials = loadBip39Credentials("123456789", tianWallet.getWords());
        //使用TransactionEncoder对RawTransaction进行签名操作
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        //转换成0x开头的字符串
        String string = Numeric.toHexString(signedMessage);
        return string;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.navigation, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.navigation_backpack:
                if (backpackFragment == null) {
                    backpackFragment = BackpackFragment.newInstance("0", "0");
                }
                FragmentUtils.show(getSupportFragmentManager(), R.id.mFrameLayout, backpackFragment);
                break;
            case R.id.navigation_home:
                if (homeFragment == null) {
                    homeFragment = HomeFragment.newInstance("0", "0");
                }
                FragmentUtils.show(getSupportFragmentManager(), R.id.mFrameLayout, homeFragment);
                break;
//            case R.id.navigation_neo:
//                if (neoFragment == null) {
//                    neoFragment = NeoWalletFragment.newInstance("0", "0");
//                }
//                FragmentUtils.show(getSupportFragmentManager(), R.id.mFrameLayout, neoFragment);
//                break;
//            case R.id.navigation_gameinfo:
//                if (gameInfoFragment == null) {
//                    gameInfoFragment = GameInfoFragment.newInstance("1", "1");
//                }
//                FragmentUtils.show(getSupportFragmentManager(), R.id.mFrameLayout, gameInfoFragment);
//                break;
            case R.id.navigation_opennbox:
                if (openBoxFragment == null) {
                    openBoxFragment = OpenBoxFragment.newInstance("2", "2");
                }
                FragmentUtils.show(getSupportFragmentManager(), R.id.mFrameLayout, openBoxFragment);
                break;
            case R.id.navigation_market:
//                if (marketFragment == null){
//                    marketFragment = MarketFragment.newInstance("2","2");
//                }
//                FragmentUtils.show(getSupportFragmentManager(),R.id.mFrameLayout,marketFragment);
                startActivity(new Intent(this, MarketActivity.class));
                break;
        }
        return true;
    }

    private void init() {
        int REQUEST_EXTERNAL_STORAGE = 1;
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);


        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(
                    this,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }
    }
}
